#define BABL_MAX_COST_VALUE 2000000
static double
-get_conversion_path_error (BablList *path);
+init_path_instrumentation (Babl *fmt_source,
+ Babl *fmt_destination);
+
+static void
+destroy_path_instrumentation (void);
+
+static void
+get_path_instrumentation (BablList *path,
+ double *path_cost,
+ double *ref_cost,
+ double *path_error);
static long
process_conversion_path (BablList *path,
{
/* We have found a candidate path, let's
* see about it's properties */
- double temp_cost = 0.0;
- double temp_error = 1.0;
+ double path_cost = 0.0;
+ double ref_cost = 0.0;
+ double path_error = 1.0;
int i;
for (i = 0; i < babl_list_size (current_path); i++)
{
- temp_error *= (1.0 + babl_conversion_error ((BablConversion *) current_path->items[i]));
- temp_cost += babl_conversion_cost ((BablConversion *) current_path->items[i]);
+ path_error *= (1.0 + babl_conversion_error ((BablConversion *) current_path->items[i]));
}
- if (temp_cost < fish_path->fish_path.cost &&
- temp_error - 1.0 <= legal_error () && /* check this before the next;
- which does a more accurate
- measurement of the error */
- (temp_error = get_conversion_path_error (current_path)) <= legal_error ()
- )
+ if (path_error - 1.0 <= legal_error ()) /* check this before the next;
+ which does a more accurate
+ measurement of the error */
{
- /* We have found the best path so far,
- * let's copy it into our new fish */
- fish_path->fish_path.cost = temp_cost;
- fish_path->fish.error = temp_error;
- babl_list_copy (current_path, fish_path->fish_path.conversion_list);
+ get_path_instrumentation (current_path, &path_cost, &ref_cost, &path_error);
+
+ if ((path_cost < ref_cost) && /* do not use paths that took longer to compute than reference */
+ (path_cost < fish_path->fish_path.cost) &&
+ (path_error <= legal_error ()))
+ {
+ /* We have found the best path so far,
+ * let's copy it into our new fish */
+ fish_path->fish_path.cost = path_cost;
+ fish_path->fish.error = path_error;
+ babl_list_copy (current_path, fish_path->fish_path.conversion_list);
+ }
}
}
else
if (!next_format->format.visited)
{
/* next_format is not in the current path, we can pay a visit */
- babl_list_insert_last (current_path, next_conversion);
- get_conversion_path (next_format, current_length + 1, max_length);
- babl_list_remove_last (current_path);
- }
-
+ babl_list_insert_last (current_path, next_conversion);
+ get_conversion_path (next_format, current_length + 1, max_length);
+ babl_list_remove_last (current_path);
+ }
}
/* Remove the current format from current path */
to_format = (Babl *) destination;
get_conversion_path ((Babl *) source, 0, max_path_length ());
+ destroy_path_instrumentation ();
babl_list_destroy (current_path);
return n;
}
-#define NUM_TEST_PIXELS (128 + 16 + 16)
+#define NUM_TEST_PIXELS (256 + 16 + 16)
static double *
test_create (void)
{
static double test[sizeof (double) * NUM_TEST_PIXELS * 4];
- static int flag = 0;
int i, j;
/* There is no need to generate the test
* more times ... */
- if (flag)
- return test;
- flag = 1;
srandom (20050728);
/* add 128 pixels in the valid range between 0.0 and 1.0 */
- for (i = 0; i < 128 * 4; i++)
+ for (i = 0; i < 256 * 4; i++)
test [i] = (double) random () / RAND_MAX;
/* add 16 pixels between -1.0 and 0.0 */
return test;
}
+// FishPath instrumentation
+
+static Babl *fmt_rgba_double = NULL;
+static double *test = NULL;
+static void *source;
+static void *destination;
+static void *ref_destination;
+static double *destination_rgba_double;
+static double *ref_destination_rgba_double;
+static Babl *fish_rgba_to_source;
+static Babl *fish_reference;
+static Babl *fish_destination_to_rgba;
+static double reference_cost;
+static int init_instrumentation_done = 0;
+
static double
-get_conversion_path_error (BablList *path)
+init_path_instrumentation (Babl *fmt_source,
+ Babl *fmt_destination)
{
- Babl *fmt_rgba_double = babl_format_new (
- babl_model ("RGBA"),
- babl_type ("double"),
- babl_component ("R"),
- babl_component ("G"),
- babl_component ("B"),
- babl_component ("A"),
- NULL);
-
- double error = 0.0;
-
- Babl *fmt_source = (Babl *) BABL (babl_list_get_first (path))->conversion.source;
- Babl *fmt_destination = (Babl *) BABL (babl_list_get_last (path))->conversion.destination;
-
- double *test;
- void *source;
- void *destination;
- double *destination_rgba_double;
- void *ref_destination;
- double *ref_destination_rgba_double;
-
- Babl *fish_rgba_to_source = babl_fish_reference (fmt_rgba_double,
- fmt_source);
- Babl *fish_reference = babl_fish_reference (fmt_source,
- fmt_destination);
- Babl *fish_destination_to_rgba = babl_fish_reference (fmt_destination,
- fmt_rgba_double);
-
- test = test_create ();
+ long ticks_start = 0;
+ long ticks_end = 0;
+
+ if (!fmt_rgba_double)
+ {
+ fmt_rgba_double = babl_format_new (
+ babl_model ("RGBA"),
+ babl_type ("double"),
+ babl_component ("R"),
+ babl_component ("G"),
+ babl_component ("B"),
+ babl_component ("A"),
+ NULL);
+ }
+
+ if (!test)
+ test = test_create ();
+
+ fish_rgba_to_source = babl_fish_reference (fmt_rgba_double,
+ fmt_source);
+ fish_reference = babl_fish_reference (fmt_source,
+ fmt_destination);
+ fish_destination_to_rgba = babl_fish_reference (fmt_destination,
+ fmt_rgba_double);
source = babl_calloc (NUM_TEST_PIXELS,
fmt_source->format.bytes_per_pixel);
test, source, NUM_TEST_PIXELS);
/* calculate the reference buffer of how it should be */
+ ticks_start = babl_ticks ();
babl_process (fish_reference,
source, ref_destination, NUM_TEST_PIXELS);
+ ticks_end = babl_ticks ();
+ reference_cost = babl_process_cost (ticks_start, ticks_end);
+
+ /* transform the reference destination buffer to RGBA */
+ babl_process (fish_destination_to_rgba,
+ ref_destination, ref_destination_rgba_double, NUM_TEST_PIXELS);
+}
+
+static void
+destroy_path_instrumentation (void)
+{
+ if (init_instrumentation_done)
+ {
+ babl_free (source);
+ babl_free (destination);
+ babl_free (destination_rgba_double);
+ babl_free (ref_destination);
+ babl_free (ref_destination_rgba_double);
+
+ /* nulify the flag for potential new search */
+ init_instrumentation_done = 0;
+ }
+}
+
+static void
+get_path_instrumentation (BablList *path,
+ double *path_cost,
+ double *ref_cost,
+ double *path_error)
+{
+ long ticks_start = 0;
+ long ticks_end = 0;
+
+ if (!init_instrumentation_done)
+ {
+ /* this initialization can be done only once since the
+ * source and destination formats do not change during
+ * the search */
+ Babl *fmt_source = (Babl *) BABL (babl_list_get_first (path))->conversion.source;
+ Babl *fmt_destination = (Babl *) BABL (babl_list_get_last (path))->conversion.destination;
+ init_path_instrumentation (fmt_source, fmt_destination);
+ init_instrumentation_done = 1;
+ }
/* calculate this path's view of what the result should be */
+ ticks_start = babl_ticks ();
process_conversion_path (path, source, destination, NUM_TEST_PIXELS);
+ ticks_end = babl_ticks ();
+ *path_cost = babl_process_cost (ticks_start, ticks_end);
/* transform the reference and the actual destination buffers to RGBA
* for comparison with each other
*/
- babl_process (fish_destination_to_rgba,
- ref_destination, ref_destination_rgba_double, NUM_TEST_PIXELS);
babl_process (fish_destination_to_rgba,
destination, destination_rgba_double, NUM_TEST_PIXELS);
- error = babl_rel_avg_error (destination_rgba_double,
- ref_destination_rgba_double,
- NUM_TEST_PIXELS * 4);
+ *path_error = babl_rel_avg_error (destination_rgba_double,
+ ref_destination_rgba_double,
+ NUM_TEST_PIXELS * 4);
fish_rgba_to_source->fish.processings--;
fish_reference->fish.processings--;
fish_reference->fish.pixels -= NUM_TEST_PIXELS;
fish_destination_to_rgba->fish.pixels -= 2 * NUM_TEST_PIXELS;
- babl_free (source);
- babl_free (destination);
- babl_free (destination_rgba_double);
- babl_free (ref_destination);
- babl_free (ref_destination_rgba_double);
-
- return error;
+ *ref_cost = reference_cost;
}